using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class EE_MainCamera_Controller : MonoBehaviour
{
    private static EE_MainCamera_Controller instance = null; public static EE_MainCamera_Controller Instance { get { return instance; } }

    [SerializeField] private Camera camera = null;
    [SerializeField] private float moveSpeed = 20f;
    [SerializeField] private float moveSmooth = 5f;
    [SerializeField] private float zoomSpeed = 40f;
    [SerializeField] private float zoomSmooth = 5f;
    
    private Controller inputs = null;

    private bool zooming = false;
    private bool moving = false;
    private Vector3 center = Vector3.zero;
    private float right = 10;
    private float left = 10;
    private float up = 10;
    private float down = 10;
    private float angle = 45;
    private float zoom = 5;
    private float zoomMax = 10;
    private float zoomMin = 1;
    private Vector2 zoomPositionOnScreen = Vector2.zero;
    private Vector3 zoomPositionInWorld = Vector3.zero;
    private float zoomBaseValue = 0;
    private float zoomBaseDistance = 0;

    private Transform root = null;
    private Transform pivot = null;
    private Transform target = null;

    private bool building = false;

    public bool isPlacingBuilding
    {
        get { return building; }
        set { building = value; }
    }

    private Vector3 buildBasePosition = Vector3.zero;
    private bool movingBuilding = false;

    void Awake()
    {
        instance = this;
        inputs = new Controller();
        root = new GameObject("CameraHelper").transform;
        pivot = new GameObject("CameraPivot").transform;
        target = new GameObject("CameraTarget").transform;
        // 设置摄像机为正交摄像机
        camera.orthographic = true;
        camera.nearClipPlane = 0; // 不管多近的物体都能看到
    }

    void OnEnable()
    {
        inputs.Enable();
        inputs.Main.Move.started += _ => MoveStarted(); // 移动开始函数注册
        inputs.Main.Move.canceled += _ => MoveCanceled(); // 移动结束函数注册
        inputs.Main.TouchZoom.started += _ => ZoomStarted(); // 缩放开始函数注册
        inputs.Main.TouchZoom.canceled += _ => ZoomCanceled(); // 缩放结束函数注册

        inputs.Main.PointerClick.performed += _ => ScreenClicked();
    }

    private void OnDisable()
    {
        inputs.Main.Move.started -= _ => MoveStarted(); // 移动开始函数注册
        inputs.Main.Move.canceled -= _ => MoveCanceled(); // 移动结束函数注册
        inputs.Main.TouchZoom.started -= _ => ZoomStarted(); // 缩放开始函数注册
        inputs.Main.TouchZoom.canceled -= _ => ZoomCanceled(); // 缩放结束函数注册

        inputs.Main.PointerClick.performed -= _ => ScreenClicked();
        inputs.Disable();
    }

    private void Start()
    {
        // Initialize(Vector3.zero, 10, 10, 10, 10, 45, 5, 3, 10);
        Initialize(Vector3.zero, 40, 40, 40, 40, 45, 10, 5, 20);
    }

    private void Initialize(Vector3 center, float right, float left, float up, float down, float angle,
        float zoom, float zoomMin, float zoomMax)
    {
        this.center = center;
        this.right = right;
        this.left = left;
        this.up = up;
        this.down = down;
        this.angle = angle;

        this.zoom = zoom;
        this.zoomMin = zoomMin;
        this.zoomMax = zoomMax;
        camera.orthographicSize = this.zoom;
        zooming = false;
        moving = false;

        pivot.parent = root;
        target.parent = pivot;
        // 控制移动
        root.position = this.center;
        root.localEulerAngles = Vector3.zero;
        // 控制视角
        pivot.localPosition = Vector3.zero;
        pivot.localEulerAngles = new Vector3(this.angle, 0, 0);
        // 摄像机跟踪目标
        target.localPosition = new Vector3(0, 0, -100); // -10
        target.localEulerAngles = Vector3.zero;
    }

    private void ScreenClicked()
    {
        Vector2 position = inputs.Main.PointerPosition.ReadValue<Vector2>();
        // eventSystem 检测屏幕点击射线, 投射在UI界面上的数量
        PointerEventData data = new PointerEventData(EventSystem.current);
        data.position = position;
        List<RaycastResult> results = new List<RaycastResult>();
        EventSystem.current.RaycastAll(data, results);
        if (results.Count < 1)
        {
            bool clickedPlane = true; // 点击的是地板
            List<EE_Building_Controller> buildings = EE_UI_Main.Instance.grid.buildings;
            for (int i = 0; i < buildings.Count; i++)
            {
                Vector3 planePosition = CameraScreenPositionToPlanePosition(position);
                if (EE_UI_Main.Instance.grid.IsPlanePositionInnerRectangle(
                        planePosition, buildings[i].CurrentX, buildings[i].CurrentY,
                        buildings[i].Rows, buildings[i].Cols))
                {
                    clickedPlane = false; // 设置为：点击的是建筑
                    if (EE_Building_Controller.Instance == null || EE_Building_Controller.Instance.IsConfirmed)
                    {
                        // 前一个建筑确认已被建造 或 前一个建筑被取消建造销毁
                        EE_Building_Controller.Instance = buildings[i];
                        building = true;// 设置为 建造状态
                    }
                    buildings[i].Selected();
                    break;
                }
            }
            if (clickedPlane)
            {
                // 点击了plane地板, 建筑取消选择
                if (EE_Building_Controller.Instance != null)
                {
                    EE_Building_Controller.Instance.Deselected();
                }
            }
        }
        else
        {
            // 选中了UI界面, 建筑取消选择
            if (EE_Building_Controller.Instance != null)
            {
                bool isOptButtons = false;
                for (int i = 0; i < results.Count; i++)
                {
                    if (results[i].gameObject == EE_UI_BuildingOptions.Instance.ButtonInfo.gameObject)
                    {
                        isOptButtons = true;
                        break;
                    }else if (results[i].gameObject == EE_UI_BuildingOptions.Instance.ButtonRotate.gameObject)
                    {
                        isOptButtons = true;
                        break;
                    }else if (results[i].gameObject == EE_UI_BuildingOptions.Instance.ButtonUpgrade.gameObject)
                    {
                        isOptButtons = true;
                        break;
                    }
                }
                // 如果点击的时选项板内的按钮，返回
                if (isOptButtons)
                {
                    return;
                }
                EE_Building_Controller.Instance.Deselected();
            }
        }
    }

    private void MoveStarted()
    {
        // 主UI是active时，才允许移动界面
        if (EE_UI_Main.Instance.isActive)
        {
            if (building)
            {
                buildBasePosition =
                    CameraScreenPositionToPlanePosition(inputs.Main.PointerPosition.ReadValue<Vector2>());
                // 按键按下位置在建筑大小的范围内才是移动建筑, 否则就是移动摄像机
                if (EE_UI_Main.Instance.grid.IsPlanePositionInnerRectangle(
                        buildBasePosition, 
                        EE_Building_Controller.Instance.CurrentX, EE_Building_Controller.Instance.CurrentY,
                        EE_Building_Controller.Instance.Rows, EE_Building_Controller.Instance.Cols))
                {
                    EE_Building_Controller.Instance.StartMovingOnGrid();
                    movingBuilding = true;// 设置为 建筑移动状态
                }
            }

            // 没有移动建筑时，可以移动摄像机
            if (!movingBuilding)
            {
                moving = true;
            }
        }
    }

    private void MoveCanceled()
    {
        moving = false;
        movingBuilding = false;
    }

    private void ZoomStarted()
    {
        // 主UI是active时，才允许缩放界面
        if (EE_UI_Main.Instance.isActive)
        {
            Vector2 touch0 = inputs.Main.TouchPosition0.ReadValue<Vector2>();
            Vector2 touch1 = inputs.Main.TouchPosition1.ReadValue<Vector2>();
            zoomPositionOnScreen = Vector2.Lerp(touch0, touch1, 0.5f);
            zoomPositionInWorld = CameraScreenPositionToPlanePosition(zoomPositionOnScreen);
            zoomBaseValue = zoom;

            touch0.x /= Screen.width;
            touch1.x /= Screen.width;
            touch0.y /= Screen.height;
            touch1.y /= Screen.height;

            zoomBaseDistance = Vector2.Distance(touch0, touch1);
            zooming = true;
        }
    }

    private void ZoomCanceled()
    {
        zooming = false;
    }

    private void Update()
    {
        if (!Input.touchSupported)
        {
            float mouseScroll = inputs.Main.MouseScroll.ReadValue<float>();
            if (mouseScroll > 0)
            {
                zoom -= zoomSpeed * Time.deltaTime;
            }
            else if (mouseScroll < 0)
            {
                zoom += zoomSpeed * Time.deltaTime;
            }
        }

        if (zooming)
        {
            Vector2 touch0 = inputs.Main.TouchPosition0.ReadValue<Vector2>();
            Vector2 touch1 = inputs.Main.TouchPosition1.ReadValue<Vector2>();

            touch0.x /= Screen.width;
            touch1.x /= Screen.width;
            touch0.y /= Screen.height;
            touch1.y /= Screen.height;

            float currentDistance = Vector2.Distance(touch0, touch1);
            float deltaDistance = currentDistance - zoomBaseDistance;
            zoom = zoomBaseValue - (deltaDistance * zoomSpeed);

            Vector3 zoomCenter = CameraScreenPositionToPlanePosition(zoomPositionOnScreen);
            root.position += (zoomPositionInWorld - zoomCenter);
        }
        else if (moving)
        {
            Vector2 move = inputs.Main.MoveDelta.ReadValue<Vector2>();
            if (move != Vector2.zero)
            {
                move.x /= Screen.width;
                move.y /= Screen.height;
                // 摄像机移动
                root.position -= root.right.normalized * move.x * moveSpeed * zoom/zoomMax;// 新增项: zoom/zoomMax
                root.position -= root.forward.normalized * move.y * moveSpeed * zoom/zoomMax;// 新增项: zoom/zoomMax
            }
        }

        // 防止摄像机超出游戏边界
        AdjustBounds();
        // 相机缩放
        if (camera.orthographicSize != zoom)
        {
            camera.orthographicSize = Mathf.Lerp(camera.orthographicSize, zoom, zoomSmooth * Time.deltaTime);
        }

        // 设置摄像机到目标上
        if (camera.transform.position != target.position)
        {
            Vector3 velocity = Vector3.zero;
            camera.transform.position = // 修改项: 新增 velocity, 将 Lerp 改为了 SmoothDamp.
                Vector3.SmoothDamp(camera.transform.position, target.position, ref velocity, moveSmooth * Time.deltaTime);
        }

        // 是否改变相机角度
        if (camera.transform.rotation != target.rotation)
        {
            camera.transform.rotation = target.rotation;
        }

        // 正在拖动建造
        if (building && movingBuilding)
        {
            Vector3 pos = CameraScreenPositionToPlanePosition(inputs.Main.PointerPosition.ReadValue<Vector2>());
            EE_Building_Controller.Instance.UpdateGridPosition(buildBasePosition, pos);
        }
    }

    private void AdjustBounds()
    {
        // zoom = Mathf.Clamp(zoom, zoomMin, zoomMax);
        if (zoom < zoomMin)
        {
            zoom = zoomMin;
        }
        else if (zoom > zoomMax)
        {
            zoom = zoomMax;
        }

        float h = PlaneOrthographicSize();
        float w = h * camera.aspect;
        if (h > (up + down) / 2)
        {
            zoom = (up + down) / 2 * Mathf.Sin(angle * Mathf.Deg2Rad);
        }

        if (w > (left + right) / 2)
        {
            zoom = Mathf.Sin(angle * Mathf.Deg2Rad) * (left + right) / 2 / camera.aspect;
        }

        h = PlaneOrthographicSize();
        w = h * camera.aspect;
        Vector3 tr = root.position + root.right.normalized * w + root.forward.normalized * h;
        Vector3 tl = root.position - root.right.normalized * w + root.forward.normalized * h;
        Vector3 dr = root.position + root.right.normalized * w - root.forward.normalized * h;
        Vector3 dl = root.position - root.right.normalized * w - root.forward.normalized * h;
        if (tr.x > center.x + right)
        {
            root.position += Vector3.left * Mathf.Abs(tr.x - (center.x + right));
        }

        if (tl.x < center.x - left)
        {
            root.position += Vector3.right * Mathf.Abs((center.x - left) - tl.x);
        }

        if (tr.z > center.z + up)
        {
            root.position += Vector3.back * Mathf.Abs(tr.z - (center.z + up));
        }

        if (dl.z < center.z - down)
        {
            root.position += Vector3.forward * Mathf.Abs((center.z - down) - dl.z);
        }
    }

    private float PlaneOrthographicSize()
    {
        float h = zoom * 2;
        return h / Mathf.Sin(angle * Mathf.Deg2Rad) / 2;
    }

    /* 屏幕点位投射到摄像机上，摄像机该点的世界坐标 */
    private Vector3 CameraScreenPositionToWorldPosition(Vector2 position)
    {
        float h = camera.orthographicSize * 2f;
        float w = camera.aspect * h;
        // 摄像机左下角点的世界坐标
        Vector3 anchor = camera.transform.position -
                         (camera.transform.right.normalized * w / 2f) -
                         (camera.transform.up.normalized * h / 2f);
        return anchor +
               (camera.transform.right.normalized * position.x / Screen.width * w) +
               (camera.transform.up.normalized * position.y / Screen.height * h);
    }

    public Vector3 CameraScreenPositionToPlanePosition(Vector2 position)
    {
        Vector3 point = CameraScreenPositionToWorldPosition(position);
        float h = point.y - root.position.y;
        float x = h / Mathf.Sin(angle * Mathf.Deg2Rad);
        return point + camera.transform.forward.normalized * x;
    }
}